package com.hm.health.Activity;

import android.app.AlertDialog;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.provider.Settings;
import android.util.Log;
import android.widget.RadioButton;
import android.widget.Toast;

import androidx.annotation.NonNull;
import androidx.recyclerview.widget.DefaultItemAnimator;
import androidx.recyclerview.widget.DividerItemDecoration;
import androidx.recyclerview.widget.GridLayoutManager;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.OrientationHelper;
import androidx.recyclerview.widget.RecyclerView;

import com.goodix.callback.AbsOnHBDTestClientListener;
import com.goodix.comsdk.entity.MeasureResult;
import com.goodix.comsdk.sdk.OnHBDClientListener;
import com.goodix.comsdk.sdk.OnHBDDataListener;
import com.goodix.comsdk.testsdk.OnHBDTestClientListener;
import com.goodix.ini.HbdOptionIni;
import com.goodix.ini.IniFileUtils;
import com.goodix.libromablecom.sdk.DeviceDataType;
import com.goodix.libromablecom.sdk.cardiff.CardiffConstants;
import com.goodix.libromablecom.sdk.cardiff.CardiffDeviceController;
import com.goodix.libromablecom.sdk.cardiff.arguments.GetArgumentsKeyEnum;
import com.goodix.libromablecom.utils.HBDTestConstants;
import com.goodix.libtest.interfaces.DevCommCallback;
import com.goodix.libtest.interfaces.DeviceDesc;
import com.goodix.libtest.interfaces.gh31x.Gh31xDevCommCallback;
import com.goodix.libtest.interfaces.gh31x.Gh31xDevComm;
import com.goodix.libtest.utils.ArrayUtils;
import com.goodix.libtest.activities.TestActivity;
import com.goodix.libtest.utils.SettingSaver;
import com.goodix.libtest.interfaces.impl.OnDisconnectedListenerCommonImpl;
import com.goodix.utils.DefaultSpUtil;
import com.goodix.utils.MPermissionUtils;
import com.goodix.utils.SPUtils;
import com.goodix.utils.ToastUtils;
import com.goodix.comsdk.errorcode.IErrorCode;
import com.goodix.comsdk.HBDOption;
import com.goodix.comsdk.HBDStatus;
import com.goodix.comsdk.RomaDevice;
import com.goodix.comsdk.testsdk.IHBDTestClient;
import com.goodix.http.RawDataManager;
import com.goodix.iot.libbase.logger.Glog;
import com.goodix.iot.libbase.utils.BluetoothUtil;
import com.goodix.libromablecom.sdk.cardiff.CardiffEvkConfigUtils;
import com.goodix.libromablecom.sdk.cardiff.arguments.StartArgumentsKeyEnum;
import com.goodix.widget.AlertDialogEx;
import com.google.android.material.bottomnavigation.BottomNavigationView;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import com.hm.health.Activity.ecgflash.EcgFlashSummaryActivity;
import com.hm.health.Activity.ecgflash.EcgFlashTestActivity;
import com.hm.health.BLE.OnDeviceStatus;
import com.hm.health.BLE.StandardHeartRateDevice;
import com.hm.health.MyApplication;
import com.hm.health.R;
import com.hm.health.Utils.Constans;
import com.hm.health.Utils.NetStateUtil;
import com.hm.health.View.RecyclerViewDivider;
import com.hm.health.adapter.NavigationAdapter;
import com.hm.health.adapter.ToggleButtonAdapter;
import com.hm.health.entity.BleDevicesInfo;
import com.hm.health.entity.NavigationBean;
import com.hm.health.entity.arguments.InitArgumentsManager;
import com.hm.health.entity.arguments.StartArgumentsManager;
import com.hm.health.handler.FirmwareUpdateHandler;
import com.hm.health.service.CardiffServiceManager;
import com.hm.health.service.EcgFlashService;
import com.hm.health.service.NotificationDataService;
import com.hm.health.service.RawdataUploadService;
import com.hm.health.widget.InputTestConditionDialog;

import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.concurrent.Executors;

import butterknife.BindView;
import butterknife.ButterKnife;

public class HomeActivity extends BaseActivity {

    private static final String TAG = "HomeActivity";

    // Get standard compare ble device
    private static final int REQUEST_GET_COMPARE_BLE_DEVICES = 0x01;
    // Get first roma ble device
    private static final int REQUEST_GET_FIRTST_ROMA_BLE_DEVICE = 0x02;

    // Enable BLE
    private static final int REQUEST_ENABLE_BLE = 0x04;
    public static final String KEY_BLE_COMPARE_DEVICES_INFO = "com.goodix.compare_device_info";

    private static long mPressBackBtnTime = 0;

    private volatile boolean mIsRomaOk = false;
    private Context mContext;
    private ToggleButtonAdapter mToggleButtonAdapter;
    private ArrayList<BleDevicesInfo> mBleDevicesInfos = new ArrayList<>();
    private RomaDevice mRomaDevice;
    StandardHeartRateDevice mStandardHeartRateDevice;

    private volatile boolean mIsSceneDialogShown = false;

    @BindView(R.id.lvCompareDevices)
    RecyclerView mRecyclerViewCompareDevices;

    @BindView(R.id.rv_navigation)
    RecyclerView mRvNavigationView;

    @BindView(R.id.roma)
    RadioButton mRomaButton;

    @BindView(R.id.navigation)
    BottomNavigationView mBottomNavigationView;

    private NavigationAdapter mNavigationAdapter;
    private List<NavigationBean> mNavigationBeanList = new ArrayList<>();

    private boolean mIsSelectHciDevice = true;
    private IHBDTestClient mBLEHBDTestClient;
    private int mCurrentPage = 0;
    private String[] mConfigs;
    private FirmwareUpdateHandler mFirmwareUpdateHandler;
    protected NetStateUtil mNetState;

    private OnHBDClientListener onHBDClientListenerForTestList;
    private OnHBDDataListener onHBDDataListener = new OnHBDDataListener() {
        @Override
        public void onDataChanged(String dataType, int[] dataArr) {
            if (DeviceDataType.DATA_TYPE_BATTERY_INFO.equals(dataType)) {
                // Glog.d(TAG, "onDataChanged: " + dataType + ", " + Arrays.toString(dataArr));
                String voltage = String.format(Locale.ENGLISH,"%d%%", dataArr[1]);
                if (!voltage.equals(mDeviceBattery)) {
                    mDeviceBattery = voltage;
                    runOnUiThread(()-> {
                        updateDeviceStatus();
                    });
                }
            }
        }

        @Override
        public void onMeasureResult(MeasureResult result) {

        }
    };

    // 设备剩余电量
    private String mDeviceBattery = "";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Glog.i(TAG, "onCreate");
        setContentView(R.layout.activity_home);
        mContext = this;
        ButterKnife.bind(this);
        initView();
        enableUI(false);
        MyApplication.getInstance().addActivity(this);
        requestPermission();
        mBLEHBDTestClient = MyApplication.getHBDTestClient();
        mBLEHBDTestClient.registerHBDDataListener(onHBDDataListener);

        BluetoothUtil.enableBluetooth(this, REQUEST_ENABLE_BLE);
        MyApplication.getInstance().startMediaPlayer();

        Intent intent = new Intent(getApplicationContext(), RawdataUploadService.class);
        startService(intent);

        mNetState = new NetStateUtil(mContext);
    }

    private String getDefaultConfigName() {
        mConfigs = CardiffEvkConfigUtils.listConfigFiles(mContext);
        if (mConfigs.length == 0) {
            return null;
        }

        String configName = DefaultSpUtil.getValueWithDefault(mContext,
                Constans.PERFS_KEY_DEFAULT_CONFIG_NAME, mConfigs[0]);
        boolean isFind = false;
        for (String config : mConfigs) {
            if (configName.compareToIgnoreCase(config) == 0) {
                isFind = true;
                break;
            }
        }

        if (!isFind) {
            configName = mConfigs[0];
        }

        DefaultSpUtil.put(mContext, Constans.PERFS_KEY_DEFAULT_CONFIG_NAME, configName);
        return configName;
    }

    private void init() {
        HbdOptionIni hbdOptionIni = MyApplication.getHbdOptionIni();
        if (hbdOptionIni == null) {
            AlertDialogEx.Builder builder = new AlertDialogEx.Builder(mContext);
            builder.setMessage(getString(R.string.no_usable_config_files));
            builder.setPositiveButton(R.string.quit, view -> finish());
            builder.show();
            return;
        }

        // 上传文件最小行数
        int minLineCount = hbdOptionIni.getUploadFileMinLineCount();
        RawDataManager.setsMinLineCount(minLineCount);

        mRomaDevice = SPUtils.getJsonObj(mContext, Constans.PERFS_KEY_DEVICE_INFO, new RomaDevice(),
                new TypeToken<RomaDevice>() {
                }.getType());
        Glog.i(TAG, "roma device name : " + mRomaDevice.getDeviceName());
        MyApplication.getHBDTestClient().registerTestCallback(mClientListener, null);

        HBDOption option = MyApplication.getHBDTestClient().getHBDOption();
        option.setServiceUUID(hbdOptionIni.getRootServiceUuid());
        option.setNotifyUUID(hbdOptionIni.getNotifyPropertyUuid());
        option.setWriteUUID(hbdOptionIni.getWritePropertyUuid());

        if (BluetoothUtil.isBluetoothEnable(this)) {
            MyApplication.getHBDTestClient().connect(mRomaDevice);
        }

        initStandardHeartRateBLEDevice();
    }

    private void requestPermission() {
        MPermissionUtils.requestPermissionsResult(HomeActivity.this, 1,
                MPermissionUtils.PERMISSIONS_WITH_BLE,
                new MPermissionUtils.OnPermissionListener() {
                    @Override
                    public void onPermissionGranted() {
                        Log.i(TAG, "onPermissionGranted");
                        init();
                    }

                    @Override
                    public void onPermissionDenied() {
                        MyApplication.getInstance().exit();
                    }
                });
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        MPermissionUtils.onRequestPermissionsResult(requestCode, permissions, grantResults);
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    }

    private void initStandardHeartRateBLEDevice() {
        mStandardHeartRateDevice = MyApplication.getInstance().getStandardHeartRateDevice();
        if (null != mStandardHeartRateDevice) {
            mStandardHeartRateDevice.setOnDeviceStatus(mOnDeviceStatus);
        }
        getBleDevicesFromGson();
        connectStandardHeartRateDevice();
    }

    /**
     * Save BLE comparison devices to sdcard
     */
    private void saveBleDevicesToGson() {
        SPUtils.putJsonObj(mContext, KEY_BLE_COMPARE_DEVICES_INFO, mBleDevicesInfos,
                new TypeToken<ArrayList<BleDevicesInfo>>() {
                }.getType());
    }

    /**
     * Get a list of BLE comparison devices
     */
    private void getBleDevicesFromGson() {
        List<BleDevicesInfo> devicesInfos = SPUtils.getJsonObj(mContext,
                KEY_BLE_COMPARE_DEVICES_INFO, new ArrayList<>(),
                new TypeToken<List<BleDevicesInfo>>() {
                }.getType());

        mBleDevicesInfos.clear();
        mBleDevicesInfos.addAll(devicesInfos);
        mToggleButtonAdapter.notifyDataSetChanged();
    }

    private BottomNavigationView.OnNavigationItemSelectedListener mReselectedListener
            = item -> {
        mCurrentPage = item.getItemId();
        switch (item.getItemId()) {
            case R.id.navigation_home:
                switchDeviceManagerPage();
                break;
            case R.id.navigation_function_list:
                switchDemoPage();
                break;
            case R.id.navigation_person:
                switchMinePage();
                break;
            default:
                break;
        }
        return true;
    };

    private void initView() {
        setCenterTitle(R.string.home);

        mBottomNavigationView.setOnNavigationItemSelectedListener(mReselectedListener);
        GridLayoutManager gridLayoutManager = new GridLayoutManager(mContext, 1);
        mRecyclerViewCompareDevices.setLayoutManager(gridLayoutManager);
        mRecyclerViewCompareDevices.setItemAnimator(new DefaultItemAnimator());
        mRecyclerViewCompareDevices.addItemDecoration(new RecyclerViewDivider(mContext, GridLayoutManager.VERTICAL));
        mRecyclerViewCompareDevices.addItemDecoration(new RecyclerViewDivider(mContext, GridLayoutManager.HORIZONTAL));
        mToggleButtonAdapter = new ToggleButtonAdapter(mContext, mBleDevicesInfos);
        mRecyclerViewCompareDevices.setAdapter(mToggleButtonAdapter);
        getBleDevicesFromGson();
        initNavigationView();
    }

    private void initNavigationView() {
        mNavigationAdapter = new NavigationAdapter(mContext, mNavigationBeanList);
        LinearLayoutManager layoutManager = new LinearLayoutManager(this);
        mRvNavigationView.setLayoutManager(layoutManager);
        layoutManager.setOrientation(OrientationHelper.VERTICAL);
        mRvNavigationView.setAdapter(mNavigationAdapter);
        mRvNavigationView.addItemDecoration(new DividerItemDecoration(mContext, DividerItemDecoration.HORIZONTAL));
        mRvNavigationView.setItemAnimator(new DefaultItemAnimator());
        switchDeviceManagerPage();

        String lastConfig = getDefaultConfigName();
        CardiffEvkConfigUtils.loadConfig(lastConfig, mContext);
    }

    private void initHBD() {
        mBLEHBDTestClient.initHBD(InitArgumentsManager.getsInstance().getBundle());
    }

    private void initHBDWithoutReset() {
        mBLEHBDTestClient.initHBDWithoutReset(InitArgumentsManager.getsInstance().getBundle());
    }

    private void disconnectAllDevice() {
        disconnectRomaDevice();
        disconnectCompareDevice();
    }

    private void disconnectRomaDevice() {
        mBLEHBDTestClient.disconnect();
        SPUtils.putJsonObj(mContext, Constans.PERFS_KEY_DEVICE_INFO,
                new RomaDevice(), new TypeToken<RomaDevice>() {
                }.getType());
        updateDeviceStatus();
    }

    private void disconnectCompareDevice() {
        mStandardHeartRateDevice.disconnect();
        mBleDevicesInfos.clear();
        saveBleDevicesToGson();
        mToggleButtonAdapter.notifyDataSetChanged();
    }

    private void switchDeviceManagerPage() {

        setCenterTitle(R.string.device_manager);
        mNavigationBeanList.clear();

        addMainDeviceNav();
        addRefDeviceNav();
        addDisconnectAllDeviceNav();
        addWorkModeNav();
        addSwitchConfigsNav();
        addUploadDataNav();  //cancel the function, which is determined by is_upload_rawdata in ui config.
//        addOtaUpdateNav();
        addFlashReadNav();
//        addMpTestNav();
        addQuitNav();

        mNavigationAdapter.notifyDataSetChanged();
    }

    private void addBLELogcatNav() {
        Intent intent = new Intent(mContext, BLELogCatActivity.class);
        NavigationBean nav = new NavigationBean(R.mipmap.ic_extension,
                getString(R.string.ble_logcat), intent);
        nav.setCallback(item -> {
            startActivity(item.getIntent());
        });
        mNavigationBeanList.add(nav);
    }

    private void addQuitNav() {
        Intent intentLogin = new Intent(mContext, LoginActivity.class);
        intentLogin.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
        NavigationBean nav = new NavigationBean(R.mipmap.ic_exit, getString(R.string.quit), intentLogin);
        mNavigationBeanList.add(nav);
    }

    private void addOtaUpdateNav() {
        NavigationBean uploadItem = new NavigationBean(R.mipmap.update, getString(R.string.ota_update), null);
        uploadItem.setCallback(item -> {
            if ((CardiffServiceManager.isServiceRunning(mContext, EcgFlashService.class.getName())
                    || isCardiffSampling())
                    && StartArgumentsManager.getInstance().getFunctionName().compareTo(StartArgumentsKeyEnum.AppFunction_ECG) == 0) {
                ToastUtils.showShortToastMessage(mContext, getString(R.string.ecg_flash_change_tip));
                return;
            }
            if (!HBDStatus.State.STATE_INITIALIZED.equals(mBLEHBDTestClient.getHBDStatus())) {
                Toast.makeText(mContext, getString(R.string.device_error_status), Toast.LENGTH_SHORT).show();
                return;
            }
            mFirmwareUpdateHandler.startUpgrade(true);
//            startActivity(new Intent(HomeActivity.this, OtaUpdateActivity.class));
        });
        mNavigationBeanList.add(uploadItem);
    }

    private void addFlashReadNav() {
        NavigationBean uploadItem = new NavigationBean(R.mipmap.ic_rss_fead, getString(R.string.sync_ecg_data), null);
        uploadItem.setCallback(item -> {
            if ((CardiffServiceManager.isServiceRunning(mContext, EcgFlashService.class.getName())
                    || isCardiffSampling())
                    && StartArgumentsManager.getInstance().getFunctionName().compareTo(StartArgumentsKeyEnum.AppFunction_ECG) == 0) {
                ToastUtils.showShortToastMessage(mContext, getString(R.string.ecg_flash_change_tip));
                return;
            }
            if (!HBDStatus.State.STATE_INITIALIZED.equals(mBLEHBDTestClient.getHBDStatus())) {
                Toast.makeText(mContext, getString(R.string.device_error_status), Toast.LENGTH_SHORT).show();
                return;
            }
            startActivity(new Intent(HomeActivity.this, FlashReadActivity.class));
        });
        mNavigationBeanList.add(uploadItem);
    }

    private void addMpTestNav() {
        NavigationBean uploadItem = new NavigationBean(R.mipmap.mptest, getString(R.string.whole_engine_test), null);
        uploadItem.setCallback(item -> {
            if (!HBDStatus.State.STATE_INITIALIZED.equals(mBLEHBDTestClient.getHBDStatus())) {
                ToastUtils.showShortToastMessage(mContext, getString(R.string.err_no_device_to_do_mp_test));
            }
//            if (!HBDStatus.State.STATE_INITIALIZED.equals(mBLEHBDTestClient.getHBDStatus())) {
//                ToastUtils.showShortToastMessage(mContext, "设备状态异常");
//                return;
//            }
            startMpTestActivity();
        });
        mNavigationBeanList.add(uploadItem);
    }

    private void addUploadDataNav() {
        if (MyApplication.getHbdOptionIni() != null && !MyApplication.getHbdOptionIni().isUploadRawdata()) {
            return;
        }

        NavigationBean uploadItem = new NavigationBean(R.mipmap.ic_file_upload,
                getString(R.string.upload_data), null);
        uploadItem.setCallback(item -> {
            ToastUtils.showLongToastMessage(mContext, mContext.getString(R.string.upload_raw_data));
            String rootPath = Constans.ECG_FLASH_DATA_ROOT;

            File dir = new File(rootPath);
            String[] dirs = dir.list();
            if (null == dirs) {
                return;
            }

            String[] dataDirs = new String[dirs.length + 1];
            for (int i = 0; i < dirs.length; ++i) {
                dataDirs[i] = rootPath + dirs[i] + "/";
                Log.d(TAG, "dataDirs[i]=" + dataDirs[i]);
            }

            dataDirs[dirs.length] = rootPath;
            RawdataUploadService.uploadDir(mContext, dataDirs);
        });
        mNavigationBeanList.add(uploadItem);
    }

    private void addSwitchConfigsNav() {
        Intent intent;
        String configName = DefaultSpUtil.getValueWithDefault(mContext,
                Constans.PERFS_KEY_DEFAULT_CONFIG_NAME, "Cardiff_ECG");
        intent = new Intent(this, EcgFlashTestActivity.class);
        NavigationBean bean = new NavigationBean(R.mipmap.ic_switch,
                getString(R.string.switch_config), intent);
        bean.setDescription(String.format("[ %s ]", configName));
        bean.setCallback(item -> {
            if ((CardiffServiceManager.isServiceRunning(mContext, EcgFlashService.class.getName())
                    || isCardiffSampling())
                    && StartArgumentsManager.getInstance().getFunctionName().compareTo(StartArgumentsKeyEnum.AppFunction_ECG) == 0) {
                ToastUtils.showShortToastMessage(mContext, getString(R.string.ecg_flash_change_tip));
            } else {
                if (HBDStatus.State.STATE_INITING == mBLEHBDTestClient.getHBDStatus()
                        || HBDStatus.State.STATE_CONNECTING == mBLEHBDTestClient.getHBDStatus()
                        || HBDStatus.State.STATE_CONNECTED == mBLEHBDTestClient.getHBDStatus()) {
                    ToastUtils.showLongToastMessage(mContext, mBLEHBDTestClient.getHBDStatus().name());
                    return;
                }

                // list config files
                mConfigs = CardiffEvkConfigUtils.listConfigFiles(mContext);
                AlertDialog.Builder builder = new AlertDialog.Builder(mContext);
                builder.setItems(mConfigs, (dialogInterface, i) -> {
                    if (!CardiffEvkConfigUtils.loadConfig(mConfigs[i], mContext)) {
                        ToastUtils.showLongToastMessage(mContext, "Failed load config files!");
                        return;
                    }
                    item.setDescription(String.format("[ %s]", mConfigs[i]));
                    DefaultSpUtil.put(mContext, Constans.PERFS_KEY_DEFAULT_CONFIG_NAME, mConfigs[i]);
                    mNavigationAdapter.notifyDataSetChanged();
                    mRomaButton.setText(R.string.roma_init);
                    initHBD();
                    updateDeviceStatus();
                });
                builder.show();
            }
        });
        mNavigationBeanList.add(bean);
    }

    private void addWorkModeNav() {
        int workMode = InitArgumentsManager.getsInstance().getWorkMode();
        NavigationBean navigationBean = new NavigationBean(R.mipmap.ic_extension,
                getString(R.string.work_mode), null);
        String[] workModes = getResources().getStringArray(R.array.work_mode);
        if (workMode < workModes.length) {
            navigationBean.setDescription(String.format("[ %s]", workModes[workMode]));
        } else {
            Glog.e(TAG, "Invalid loadConfig type");
            ToastUtils.showShortToastMessage(mContext, "Invalid loadConfig type");
        }
        navigationBean.setCallback(item -> {
            if ((CardiffServiceManager.isServiceRunning(mContext, EcgFlashService.class.getName())
                    || isCardiffSampling())
                    && StartArgumentsManager.getInstance().getFunctionName().compareTo(StartArgumentsKeyEnum.AppFunction_ECG) == 0) {
                ToastUtils.showShortToastMessage(mContext, getString(R.string.ecg_flash_change_tip));
            } else {
                AlertDialog.Builder builder = new AlertDialog.Builder(mContext);
                String[] workModes1 = getResources().getStringArray(R.array.work_mode);
                builder.setItems(workModes1, (dialogInterface, i) -> {
                    item.setDescription(String.format("[ %s]", workModes1[i]));
                    InitArgumentsManager.getsInstance().setWorkMode(i);
                    mNavigationAdapter.notifyDataSetChanged();
                    mRomaButton.setText(R.string.roma_init);
                    initHBD();
                    updateDeviceStatus();
                });
                builder.show();
            }
        });
        mNavigationBeanList.add(navigationBean);
    }

    private void addDisconnectAllDeviceNav() {
        NavigationBean disconnectItem = new NavigationBean(R.mipmap.ic_disconnect,
                getString(R.string.disconnect_all_device), null);
        disconnectItem.setCallback(item -> disconnectAllDevice());
        mNavigationBeanList.add(disconnectItem);
    }

    private void addRefDeviceNav() {
        Intent intent;
        intent = new Intent(mContext, LeDeviceListActivity.class);
        intent.putExtra(LeDeviceListActivity.ARG_IS_SINGLE_SELECTED, false);
        intent.putExtra(Constans.EXTRA_START_ACTIVITY_FOR_RESULT, true);
        NavigationBean refDeviceItem = new NavigationBean(R.mipmap.ic_add,
                getString(R.string.select_ble_comparison_devices), intent);
        refDeviceItem.setCallback(item -> {
            String jsonStr = (String) SPUtils.get(mContext,
                    KEY_BLE_COMPARE_DEVICES_INFO, "");
            item.getIntent().putExtra(LeDeviceListActivity.ARG_BOUNDED_DEVICES, jsonStr);
            disconnectCompareDevice();
            startActivityForResult(item.getIntent(), REQUEST_GET_COMPARE_BLE_DEVICES);
        });
        mNavigationBeanList.add(refDeviceItem);
    }

    private void addMainDeviceNav() {
        Intent intent;
        intent = new Intent(mContext, LeDeviceListActivity.class);
        intent.putExtra(LeDeviceListActivity.ARG_IS_SINGLE_SELECTED, true);
        intent.putExtra(Constans.EXTRA_START_ACTIVITY_FOR_RESULT, true);
        NavigationBean mainDeviceItem = new NavigationBean(R.mipmap.ic_add,
                getString(R.string.main_device), intent);
        mainDeviceItem.setCallback(item -> {
            RomaDevice device = SPUtils.getJsonObj(mContext,
                    Constans.PERFS_KEY_DEVICE_INFO, new RomaDevice(),
                    new TypeToken<RomaDevice>() {
                    }.getType());
            String jsonStr = new Gson().toJson(new RomaDevice[]{device});
            item.getIntent().putExtra(LeDeviceListActivity.ARG_BOUNDED_DEVICES, jsonStr);
            startActivityForResult(item.getIntent(), REQUEST_GET_FIRTST_ROMA_BLE_DEVICE);
        });
        mNavigationBeanList.add(mainDeviceItem);
    }

    private void switchDemoPage() {

        if (!mIsRomaOk) {
            ToastUtils.showLongToastMessage(mContext, mBLEHBDTestClient.getHBDStatus().name());
            mBottomNavigationView.setSelectedItemId(R.id.navigation_home);
            return;
        }

        setCenterTitle(R.string.demo);
        mNavigationBeanList.clear();
        for (String functionName : CardiffEvkConfigUtils.listFunction()) {
            //心电贴
            if (functionName.compareTo(StartArgumentsKeyEnum.AppFunction_ECG) == 0) {
                Intent intent = new Intent(this, EcgFlashTestActivity.class);
                int resId = getFunctionIcon(functionName);
                NavigationBean navigationBean = new NavigationBean(resId, getString(R.string.ecg_flash_function), intent);
                navigationBean.setCallback(nav -> {
                    StartArgumentsManager.getInstance().setFunctionName(StartArgumentsKeyEnum.AppFunction_ECG);
                    showSceneDialogEx(nav.getIntent(), functionName);
                });
                mNavigationBeanList.add(navigationBean);
            }
        }
        mNavigationAdapter.notifyDataSetChanged();
    }

    private int getFunctionIcon(String functionName) {
        int resId = R.mipmap.ic_extension;
        if (functionName.compareTo(StartArgumentsKeyEnum.AppFunction_ECG) == 0) {
            resId = R.mipmap.ic_launcher;
        }
        return resId;
    }

    private void switchMinePage() {
        setCenterTitle(R.string.mine);

        mNavigationBeanList.clear();
        Intent intent;

//        intent = new Intent(this, HistorySummaryActivity.class);
//        mNavigationBeanList.add(new NavigationBean(R.mipmap.heart_rate, getString(R.string.heart_rate_records), intent));


        intent = new Intent(this, EcgFlashSummaryActivity.class);
        NavigationBean bean = new NavigationBean(R.mipmap.ic_launcher, getString(R.string.ecg_flash_history_records), intent);
        bean.setCallback(nav -> {
            if ((CardiffServiceManager.isServiceRunning(mContext, EcgFlashService.class.getName())
                    || isCardiffSampling())
                    && StartArgumentsManager.getInstance().getFunctionName().compareTo(StartArgumentsKeyEnum.AppFunction_ECG) == 0) {
                ToastUtils.showShortToastMessage(mContext, getString(R.string.ecg_flash_change_tip));
            } else {

                startActivity(nav.getIntent());
            }
        });
        mNavigationBeanList.add(bean);

//        intent = new Intent(this, AlgorithmSimulationActivity.class);
//        mNavigationBeanList.add(new NavigationBean(R.mipmap.ic_extension, getString(R.string.algorithm_simulation), intent));
//
//        intent = new Intent(this, DeviceConfigDeliveryActivity.class);
//        mNavigationBeanList.add(new NavigationBean(R.mipmap.ic_extension, getString(R.string.send_device_config), intent));
//
//        addBLELogcatNav();

        intent = new Intent(this, AboutActivity.class);
        mNavigationBeanList.add(new NavigationBean(R.mipmap.ic_about, getString(R.string.app_about), intent));

        intent = new Intent(Settings.ACTION_ACCESSIBILITY_SETTINGS);
        mNavigationBeanList.add(new NavigationBean(R.mipmap.ic_extension, getString(R.string.keep_live), intent));

        mNavigationAdapter.notifyDataSetChanged();
    }

    private void enableUI(boolean enable, String message) {
        mRomaButton.setText(message);
        if (!enable) {
            mRomaButton.setTextColor(getResources().getColor(R.color.device_disconnected));
            mRomaButton.setChecked(false);
            mRomaButton.setSelected(false);
        } else {
            mRomaButton.setTextColor(getResources().getColor(R.color.device_connected));
            mRomaButton.setChecked(true);
            mRomaButton.setSelected(true);
        }
        enableUI(enable);
    }

    private void enableUI(boolean b) {
//        mRomaButton.setEnabled(b);
        if (b) {
            if (!mDeviceBattery.isEmpty()) {
                String message = mRomaButton.getText().toString();
                message = String.format(Locale.ENGLISH, "%s (%s %s)", message, getResources().getString(R.string.battery), mDeviceBattery);
                mRomaButton.setText(message);
            }
        }
    }

    @Override
    protected void onStart() {
        super.onStart();
        mBLEHBDTestClient.registerTestCallback(mClientListener, null);
        reinitStandardHRDeviceStatus();
        reinitRomaDevice();
        if (onHBDClientListenerForTestList != null) {
            mBLEHBDTestClient.unRegisterTestCallback(onHBDClientListenerForTestList, null);
            onHBDClientListenerForTestList = null;
        }
    }

    private void reinitRomaDevice() {
        mRomaDevice = SPUtils.getJsonObj(mContext, Constans.PERFS_KEY_DEVICE_INFO,
                new RomaDevice(), new TypeToken<RomaDevice>() {
                }.getType());
        updateDeviceStatus();
    }

    private void updateDeviceStatus() {
        String message;
        IHBDTestClient client = MyApplication.getHBDTestClient();
//        String deviceName = client.getRomaDevice().getDeviceName();
        String deviceName = "";
        HBDStatus.State state = client.getHBDStatus();
        Glog.i(TAG, "updateDeviceStatus:" + state);
        mIsRomaOk = false;
        switch (state) {
            case STATE_IDLE:
            case STATE_DISCONNECTED:
            case STATE_ERROR:
                message = getString(R.string.device_status_disconnected);
                message = String.format(Locale.ENGLISH, "%s %s", deviceName, message);
                enableUI(false, message);
                break;
            case STATE_INITING:
                message = getString(R.string.device_status_initing);
                message = String.format(Locale.ENGLISH, "%s %s", deviceName, message);
                enableUI(false, message);
                break;
            case STATE_CONNECTING:
            case STATE_CONNECTED:
                message = getString(R.string.device_status_connecting);
                message = String.format(Locale.ENGLISH, "%s %s", deviceName, message);
                enableUI(false, message);
                break;
            case STATE_INITIALIZED:
                message = getString(R.string.roma_connected);
                message = String.format(Locale.ENGLISH, "%s %s", deviceName, message);
                enableUI(true, message);
                mIsRomaOk = true;
                break;
            default:
                message = getString(R.string.device_status_connected);
                message = String.format(Locale.ENGLISH, "%s %s", deviceName, message);
                enableUI(true, message);
                mIsRomaOk = true;
                break;
        }
    }

    private void reinitStandardHRDeviceStatus() {
        if (null != mStandardHeartRateDevice) {
            mStandardHeartRateDevice.setOnDeviceStatus(mOnDeviceStatus);
            Map<String, Boolean> mapBleDevviceStatus = mStandardHeartRateDevice.getDeviceStatusMap();
            for (int i = 0; i < mBleDevicesInfos.size(); ++i) {
                if (mapBleDevviceStatus.containsKey(mBleDevicesInfos.get(i).getDeviceAddress())) {
                    boolean isConnected = mapBleDevviceStatus.get(mBleDevicesInfos.get(i).getDeviceAddress());
                    mBleDevicesInfos.get(i).setConnected(isConnected);
                }
            }
            mToggleButtonAdapter.notifyDataSetChanged();
        }
    }

    private void connectStandardHeartRateDevice() {
        if (null != mStandardHeartRateDevice) {
            for (BleDevicesInfo bleDevicesInfo : mBleDevicesInfos) {
                mStandardHeartRateDevice.connect(bleDevicesInfo.getDeviceAddress());
            }
        }
    }

    @Override
    protected void onPause() {
        super.onPause();
    }

    @Override
    protected void onStop() {
        super.onStop();
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        Log.d(TAG, "onDestroy:");
        if (null != mStandardHeartRateDevice) {
            mStandardHeartRateDevice.setOnDeviceStatus(null);
        }

        Intent intent = new Intent(getApplicationContext(), RawdataUploadService.class);
        stopService(intent);

        saveBleDevicesToGson();
        stopService(new Intent(mContext, NotificationDataService.class));
        IHBDTestClient hbdTestClient = MyApplication.getHBDTestClient();
        hbdTestClient.unRegisterTestCallback(mClientListener, null);

        if (null != mFirmwareUpdateHandler) {
            mFirmwareUpdateHandler.cancel();
        }

        mBLEHBDTestClient.unRegisterHBDDataListener(onHBDDataListener);

        if (null != mNetState) {
            mNetState.unregisterNetReceiver();
        }
    }

    private void showSceneDialogEx(Intent intent, String functionName) {
        Log.i(TAG, "showSceneDialog");
        if (mIsSceneDialogShown) {
            return;
        }
        mIsSceneDialogShown = true;

        boolean editable = true;
        if (functionName.compareTo(StartArgumentsKeyEnum.AppFunction_ECG) == 0) {
            if (CardiffServiceManager.isServiceRunning(mContext, EcgFlashService.class.getName())
                    /*|| isCardiffSampling()*/) {
                editable = false;
            }
        }
        final InputTestConditionDialog confirmDialog = new InputTestConditionDialog(this, editable);
        confirmDialog.setClicklistener(new InputTestConditionDialog.ClickListenerInterface() {

            @Override
            public void doConfirm(String subjectName, int sceneID,
                                  String sceneName, int earHangID,
                                  String earHangName,
                                  int algCalculateStrategy,
                                  int measurementMode) {
                if (!mIsRomaOk) {
                    confirmDialog.dismiss();
                    ToastUtils.showShortToastMessage(getApplicationContext(), getString(R.string.roma_disconnected));
                    return;
                }
                Log.i(TAG, "doConfirm : " +
                        "subjectName = " + subjectName
                        + " ; sceneName = " + sceneName
                        + "; earHangName " + earHangName);
                MyApplication.getInstance().setSubjectName(subjectName);
                MyApplication.getInstance().setEarhang(earHangName);
                StartArgumentsManager.getInstance().setAlgCalculateStrategy(algCalculateStrategy);
                StartArgumentsManager.getInstance().setSceneName(sceneName);
                StartArgumentsManager.getInstance().setMeasurementMode(measurementMode);
                confirmDialog.dismiss();
                mContext.startActivity(intent);
            }

            @Override
            public void doCancel() {
                confirmDialog.dismiss();

            }
        });
        confirmDialog.setOnDismissListener(dialogInterface -> {
            Log.d(TAG, "dialog onDismiss");
            mIsSceneDialogShown = false;
        });
        confirmDialog.setIsSelectHciDevice(mIsSelectHciDevice);
        Log.d(TAG, "showSceneDialog show");
        confirmDialog.setCanceledOnTouchOutside(false);
        confirmDialog.show();
    }

    private AbsOnHBDTestClientListener mClientListener = new AbsOnHBDTestClientListener() {
        @Override
        public void onHBDInitialized(int errCode) {
            if (errCode == IErrorCode.SUCCESS) {
                Log.d(TAG, "onHBDInitialized");
                mIsRomaOk = true;

                RomaDevice romaDevice = MyApplication.getHBDTestClient().getRomaDevice();
                String deviceName = romaDevice.getDeviceName();
                if ((null == deviceName) || (deviceName.isEmpty())) {
                    mRomaButton.setText(R.string.roma_connected);
                } else {
                    mRomaButton.setText(String.format(Locale.ENGLISH, "%s %s",
                            "", getString(R.string.connected)));
                }

                mRomaButton.setTextColor(getResources().getColor(R.color.device_connected));
                mRomaButton.setChecked(true);
                mRomaButton.toggle();
                enableUI(true);
                startService(new Intent(mContext, NotificationDataService.class));
                updateFirmware();

                Executors.newSingleThreadExecutor().execute(() -> {
                    int sampleStatus = Integer.parseInt(
                            MyApplication.getHBDTestClient().getRunTimeFlag(GetArgumentsKeyEnum.ARG_GET_SLAVER_SAMPLE_STATUS));
                    Glog.i(TAG, "sampleStatus=" + sampleStatus);
                    if (StartArgumentsManager.getInstance().getFunctionName().compareTo(StartArgumentsKeyEnum.AppFunction_ECG) == 0) {
                        if (sampleStatus == CardiffConstants.CARDIFF_SAMPLE_RETURN_FREE) {
                            Glog.i(TAG, "sampleStatus=" + sampleStatus);
                            mNetState.registerNetReceiver();
                        } else if (sampleStatus == CardiffConstants.CARDIFF_RETURN_NO_RESPOND) {
                            mIsRomaOk = false;
                            mRomaButton.setText(R.string.roma_init_failed);
                            mRomaButton.setTextColor(getResources().getColor(R.color.device_disconnected));
                            mRomaButton.setChecked(true);
                            mRomaButton.toggle();
                        } else {
                            String testIdEcg = MyApplication.getHBDTestClient().getRunTimeFlag(GetArgumentsKeyEnum.ALG_ECG_TEST_ID);
                            Glog.i(TAG, "testIdEcg" + testIdEcg);
                            if (testIdEcg != "FAILED") {
                                String testInfo = (String)SPUtils.get(mContext, EcgFlashService.KEY_ECG_FLASH_LOST_TESTER_INFO, "unknown-unknown");
                                Glog.i(TAG, "testInfo" + testInfo);
                                if (!testInfo.contains(testIdEcg)) {
                                    if (CardiffServiceManager.isServiceRunning(mContext, EcgFlashService.class.getName())) {
                                        Intent intent = new Intent(mContext , EcgFlashService.class);
                                        stopService(intent);
                                    }
                                    return;
                                }
                            }
                            // 恢复时启动服务
                            int start_mode = EcgFlashService.BLE_DISCONNECTED_START;
                            if (!CardiffServiceManager.isServiceRunning(mContext, EcgFlashService.class.getName())) {
                                start_mode = EcgFlashService.CRASH_START;
                            }
                            Glog.i(TAG, "start_mode=" + start_mode);
                            Intent intent = new Intent(mContext , EcgFlashService.class);
                            intent.putExtra(EcgFlashService.EXT_START_MODE, start_mode);
                            startService(intent);
                        }
                    }
                });
            } else {
                Log.d(TAG, "onHBDInitialized errCode=" + errCode);
                mIsRomaOk = false;
                mRomaButton.setText(R.string.roma_init_failed);
                mRomaButton.setTextColor(getResources().getColor(R.color.device_disconnected));
                mRomaButton.setChecked(true);
                mRomaButton.toggle();
            }
        }

        @Override
        public void onConnecting(int nErrorCode) {
            if (nErrorCode == IErrorCode.SUCCESS) {
                Log.d(TAG, "onConnecting");
                mRomaButton.setText(R.string.connecting);
                mRomaButton.setTextColor(getResources().getColor(R.color.device_disconnected));
            }
            mIsRomaOk = false;
        }

        @Override
        public void onConnected(int errCode) {
            if (errCode == IErrorCode.SUCCESS && !mIsRomaOk) {
                Log.d(TAG, "onConnected");
                mRomaButton.setText(R.string.roma_init);
                mRomaButton.setTextColor(getResources().getColor(R.color.device_disconnected));
                initHBD();
            }
        }

        @Override
        public void onDisconnected(int errCode) {
            Log.d(TAG, "onDisconnected");
            mIsRomaOk = false;
            mRomaButton.setText(R.string.roma_disconnected);
            mRomaButton.setTextColor(getResources().getColor(R.color.device_disconnected));
            mRomaButton.setChecked(false);
            mRomaButton.setSelected(false);
            enableUI(false);
            mBottomNavigationView.setSelectedItemId(R.id.navigation_home);
            stopService(new Intent(mContext, NotificationDataService.class));
            if (CardiffServiceManager.isServiceRunning(mContext, EcgFlashService.class.getName())) {
                Intent intent = new Intent(mContext , EcgFlashService.class);
                stopService(intent);
            }
        }

        @Override
        public void onError(int errCode, String message) {
            Log.d(TAG, "onError");
            ToastUtils.showShortToastMessage(mContext, message);
        }
    };

    private void updateFirmware() {
        if (null != mFirmwareUpdateHandler) {
            mFirmwareUpdateHandler.cancel();
        }
        mFirmwareUpdateHandler = new FirmwareUpdateHandler(mContext, mBLEHBDTestClient);
        mFirmwareUpdateHandler.startUpgrade(false);
    }

    private boolean isCardiffSampling() {
        int sampling = Integer.parseInt(
                MyApplication.getHBDTestClient().getRunTimeFlag(GetArgumentsKeyEnum.ARG_GET_SLAVER_SAMPLE_STATUS));
        if (sampling != CardiffConstants.CARDIFF_SAMPLE_RETURN_FREE
            && sampling != CardiffConstants.CARDIFF_RETURN_NO_RESPOND) {
            return true;
        } else {
            return false;
        }
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        Log.d(TAG, "onActivityResult()");
        if (resultCode != RESULT_OK) {
            return;
        }

        switch (requestCode) {
            case REQUEST_GET_COMPARE_BLE_DEVICES: {
                // Get selected first roma ble device
                onGetCompareBleDevices(data);
                break;
            }
            case REQUEST_GET_FIRTST_ROMA_BLE_DEVICE: {
                onGetFirstRomaDevice(data);
                break;
            }
            case REQUEST_ENABLE_BLE: {
                MyApplication.getHBDTestClient().connect(mRomaDevice);
                break;
            }
            default:
                break;
        }
    }

    private void onGetFirstRomaDevice(Intent data) {

        Log.d(TAG, "onGetFirstRomaDevice");

        if (null == data) {
            Log.e(TAG, "onGetFirstRomaDevice, but intent data is NULL");
            return;
        }

        String jsonStr = data.getStringExtra(LeDeviceListActivity.SELECTED_BLE_DEVICES);
        List<BleDevicesInfo> devicesInfos = new Gson().fromJson(jsonStr, new TypeToken<List<BleDevicesInfo>>() {
        }.getType());
        if (null == devicesInfos || devicesInfos.size() == 0) {
            Log.d(TAG, "devicesInfos is empty");
            return;
        }

        BleDevicesInfo devicesInfo = devicesInfos.get(0);
        if (MyApplication.getHBDTestClient().isDeviceConnected(devicesInfo)) {
            Log.d(TAG, "device:" + devicesInfo.getDeviceAddress() + " already connected.");
            return;
        }

        mRomaDevice.setDeviceAddress(devicesInfo.getDeviceAddress());
        mRomaDevice.setDeviceName(devicesInfo.getDeviceName());
        mRomaDevice.setDeviceType(devicesInfo.getDeviceType());

        Log.d(TAG, "begin to connect device");
        MyApplication.getHBDTestClient().connect(mRomaDevice);
        SPUtils.putJsonObj(mContext, Constans.PERFS_KEY_DEVICE_INFO, mRomaDevice,
                new TypeToken<RomaDevice>() {
                }.getType());
    }

    private void onGetCompareBleDevices(Intent data) {
        if (null == data) {
            return;
        }

        mBleDevicesInfos.clear();
        saveBleDevicesToGson();

        String jsonStr = data.getStringExtra(LeDeviceListActivity.SELECTED_BLE_DEVICES);
        List<BleDevicesInfo> listDevices = new Gson().fromJson(jsonStr,
                new TypeToken<List<BleDevicesInfo>>() {
                }.getType());
        if (null != listDevices) {
            listDevices.size();
            mBleDevicesInfos.clear();
            mBleDevicesInfos.addAll(listDevices);
            mToggleButtonAdapter.notifyDataSetChanged();

            if (null != mStandardHeartRateDevice) {
                connectStandardHeartRateDevice();
            }

            // Save selected device to file
            saveBleDevicesToGson();
        }
    }

    // The second ROMA device conenction status
    OnDeviceStatus mOnDeviceStatus = new OnDeviceStatus() {
        @Override
        public void onConnecting(final String deviceAddress, int errCode) {
            Log.d(TAG, "onConnecting.." + deviceAddress);
        }

        @Override
        public void onConnected(final String deviceAddress, int errCode) {
            Log.d(TAG, "onConnected.." + deviceAddress);
            runOnUiThread(() -> reinitStandardHRDeviceStatus());
        }

        @Override
        public void onDisconnected(final String address, int errCode) {
            Log.d(TAG, "onDisconnected.." + address);
            runOnUiThread(() -> reinitStandardHRDeviceStatus());
        }

        @Override
        public void onInitialized(final String address, int errCode) {
            Log.d(TAG, "onInitialized: ");
            runOnUiThread(() -> reinitStandardHRDeviceStatus());
        }
    };

    @Override
    public void onBackPressed() {
        Log.d(TAG, "onBackPressed");
        Toast.makeText(this, "请按HOME退出", Toast.LENGTH_SHORT).show();
//        if (0 == mPressBackBtnTime) {
//            mPressBackBtnTime = System.currentTimeMillis();
//            Toast.makeText(this, getResources().getString(R.string.press_again_to_exit), Toast.LENGTH_SHORT).show();
//        } else {
//            if (System.currentTimeMillis() - mPressBackBtnTime < 1500) {
//                mPressBackBtnTime = 0;
//                SysApplication.getInstance().exit();
//            } else {
//                mPressBackBtnTime = System.currentTimeMillis();
//                Toast.makeText(this, getResources().getString(R.string.press_again_to_exit), Toast.LENGTH_SHORT).show();
//            }
//        }
    }

    //////////////////////////////////////////////////////////////

    private void startMpTestActivity() {
        class DevCommImpl implements Gh31xDevComm {
            private IHBDTestClient hbdTestClient;

            private OnHBDDataListener hbdDataListener;

            private Gh31xDevCommCallback cb;

            void setHbdTestClient(IHBDTestClient hbdTestClient) {
                this.hbdTestClient = hbdTestClient;
            }

            @Override
            public void onNext() {
                if (cb != null) {
                    cb.onNext();
                }
            }

            @Override
            public void logE(String tag, String msg) {
                Glog.e(tag, msg);
            }

            @Override
            public void logW(String tag, String msg) {
                Glog.w(tag, msg);
            }

            @Override
            public void logI(String tag, String msg) {
                Glog.i(tag, msg);
            }

            @Override
            public void logD(String tag, String msg) {
                Glog.d(tag, msg);
            }

            @Override
            public void logV(String tag, String msg) {
                Glog.v(tag, msg);
            }

            @Override
            public void logE(String tag, String msg, Throwable throwable) {
                Glog.e(tag, msg, throwable);
            }

            @Override
            public void logW(String tag, String msg, Throwable throwable) {
                Glog.w(tag, msg, throwable);
            }

            @Override
            public void logI(String tag, String msg, Throwable throwable) {
                Glog.i(tag, msg, throwable);
            }

            @Override
            public void logD(String tag, String msg, Throwable throwable) {
                Glog.d(tag, msg, throwable);
            }

            @Override
            public void logV(String tag, String msg, Throwable throwable) {
                Glog.v(tag, msg, throwable);
            }

            @Override
            public DevCommCallback getCallBack() {
                return cb;
            }

            @Override
            public void setCallBack(DevCommCallback cb) {
                this.cb = (Gh31xDevCommCallback) cb;
                if (hbdDataListener != null) {
                    hbdTestClient.unRegisterHBDDataListener(hbdDataListener);
                }
                if (cb != null) {
                    hbdTestClient.registerHBDDataListener(hbdDataListener = new OnHBDDataListener() {
                        @Override
                        public void onDataChanged(String dataType, int[] dataArr) {
                            DevCommImpl.this.cb.onReceivingData(dataType, dataArr);
                        }

                        @Override
                        public void onMeasureResult(MeasureResult result) {
                            if ("Lead state".equalsIgnoreCase(result.mTitle)) {
                                if ("OFF".equalsIgnoreCase(result.mValue)) {
                                    DevCommImpl.this.cb.onLeadOff();
                                } else if ("ON".equalsIgnoreCase(result.mValue)) {
                                    DevCommImpl.this.cb.onLeadOn();
                                }
                            }
                        }
                    });
                }
            }

            @Override
            public boolean init(String configFileName) {
                Glog.i(TAG, "configFileName = " + configFileName);
                if (!configFileName.endsWith(".ini")) {
                    throw new IllegalArgumentException("Illegal config file name: " + configFileName);
                }
                boolean[] isFinishedAndResult = {false, true}; // result为true表示【有】问题。
                final long MAX_WAIT_TIME = 12000L;
                OnHBDClientListener clientListener = new AbsOnHBDTestClientListener() {
                    @Override
                    public void onHBDInitialized(int errCode) {
                        isFinishedAndResult[0] = true;
                        isFinishedAndResult[1] = errCode != IErrorCode.SUCCESS;
                    }

                    @Override
                    public void onError(int errCode, String message) {
                        isFinishedAndResult[0] = true;
                        isFinishedAndResult[1] = true;
                    }

                    @Override
                    public void onDisconnected(int errCode) {
                        isFinishedAndResult[0] = true;
                        isFinishedAndResult[1] = true;
                    }
                };
                mBLEHBDTestClient.registerTestCallback(clientListener, null);
                try {
                    if (!CardiffEvkConfigUtils.loadConfig(configFileName, mContext)) {
                        return true;
                    }
                    mBLEHBDTestClient.initHBD(InitArgumentsManager.getsInstance().getBundle());
                    long startTime = System.currentTimeMillis();
                    while (!isFinishedAndResult[0] && System.currentTimeMillis() - startTime < MAX_WAIT_TIME) {
                        try {
                            Thread.sleep(50);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                    if (!isFinishedAndResult[0]) {
                        return true;
                    } else {
                        return isFinishedAndResult[1];
                    }
                } finally {
                    mBLEHBDTestClient.unRegisterTestCallback(clientListener, null);
                }
            }

            @Override
            public void startCaptureData(String functionName) {
                StartArgumentsManager manager = StartArgumentsManager.getInstance();
                manager.setFunctionName(functionName);
                manager.setSceneName(getString(R.string.motionless));
                // 如果之前的停止操作没有完成，这里等待一段时间。
                final long MAX_WAIT_TIME = 2000L;
                long startTime = System.currentTimeMillis();
                while (!HBDStatus.State.STATE_INITIALIZED.equals(hbdTestClient.getHBDStatus()) && System.currentTimeMillis() - startTime <= MAX_WAIT_TIME) {
                    try {
                        Thread.sleep(50);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                hbdTestClient.startHBD(manager.getBundle());
            }

            @Override
            public void stopCaptureData() {
                hbdTestClient.stopHBD();
            }

            @Override
            public String getFileHeader(String dataType) {
                return CardiffDeviceController.getInstance().getFileHeader(dataType).trim();
            }

            private boolean isReadRegSucceed;
            private int[] readRegResult;

            @Override
            public short[] regRead(short addr, int len) {
                isReadRegSucceed = false;
                readRegResult = null;
                OnHBDTestClientListener listener = (cmd, errCode, resultData) -> {
                    if (cmd == HBDTestConstants.HBD_CMD_CALLBACK_REG_TEST) {
                        isReadRegSucceed = errCode == IErrorCode.SUCCESS;
                        readRegResult = resultData;
                    }
                };
                try {
                    hbdTestClient.registerTestCallback(null, listener);
                    hbdTestClient.sendHBDCmd(HBDTestConstants.HBD_CMD_READ_REG, new short[]{addr, (short) len});
                    final long MAX_WAIT_TIME = 2000L;
                    long startTime = System.currentTimeMillis();
                    while (!isReadRegSucceed && System.currentTimeMillis() - startTime < MAX_WAIT_TIME) {
                        try {
                            Thread.sleep(50);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                    if (!isReadRegSucceed || readRegResult == null || readRegResult.length == 0) {
                        return null;
                    }
                    return ArrayUtils.intArr2ShortArr(readRegResult);
                } finally {
                    hbdTestClient.unRegisterTestCallback(null, listener);
                }
            }

            private boolean isWriteRegSucceed;

            @Override
            public boolean regWrite(short addr, short... data) {
                isWriteRegSucceed = false;
                OnHBDTestClientListener listener = (cmd, errCode, resultData) -> {
                    if (cmd == HBDTestConstants.HBD_CMD_CALLBACK_REG_TEST) {
                        isWriteRegSucceed = errCode == IErrorCode.SUCCESS;
                    }
                };
                try {
                    hbdTestClient.registerTestCallback(null, listener);
                    hbdTestClient.sendHBDCmd(HBDTestConstants.HBD_CMD_WRITE_REG, ArrayUtils.arrayConcat(new short[]{addr, (short) data.length}, data));
                    final long MAX_WAIT_TIME = 2000L;
                    long startTime = System.currentTimeMillis();
                    while (!isWriteRegSucceed && System.currentTimeMillis() - startTime < MAX_WAIT_TIME) {
                        try {
                            Thread.sleep(50);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                    return !isWriteRegSucceed;
                } finally {
                    hbdTestClient.unRegisterTestCallback(null, listener);
                }
            }
        }

        DevCommImpl devCommImpl = new DevCommImpl();
        devCommImpl.setHbdTestClient(mBLEHBDTestClient);
        SettingSaver.setDevComm(devCommImpl);
        SettingSaver.setDeviceDesc(new DeviceDesc() {
            @Override
            public String getDeviceMacAddress() {
                return mBLEHBDTestClient.getRomaDevice().getDeviceAddress();
            }

            @Override
            public String getDeviceName() {
                return mBLEHBDTestClient.getRomaDevice().getDeviceName();
            }

            @Override
            public String getDeviceDescription() {
                return mBLEHBDTestClient.getRomaDevice().getDeviceName();
            }

            @Override
            public boolean isDeviceReadyForTest() {
                return HBDStatus.State.STATE_INITIALIZED.equals(mBLEHBDTestClient.getHBDStatus());
            }
        });
        OnDisconnectedListenerCommonImpl onDisconnectedListenerCommonImpl = new OnDisconnectedListenerCommonImpl();
        SettingSaver.setOnDisconnectedListenerCommonImpl(onDisconnectedListenerCommonImpl);
        onHBDClientListenerForTestList = new AbsOnHBDTestClientListener() {
            @Override
            public void onDisconnected(int errCode) {
                onDisconnectedListenerCommonImpl.onDisconnecting();
            }
        };
        mBLEHBDTestClient.registerTestCallback(onHBDClientListenerForTestList, null);
        Intent intent = new Intent(mContext, TestActivity.class);
        intent.putExtra("configFilePath", new File(IniFileUtils.getDeviceConfigPath(this)));
        startActivity(intent);
    }
}
